package tool.parser
 
object Trees {
	import analyzer.Symbols._
	import analyzer.Types._
	  
	sealed trait Tree extends Positional
   
	case class Program(main: MainObject, classes: List[Class]) extends Tree
	case class MainObject(id: Identifier, stat: StatTree) extends Tree with Symbolic[ClassSymbol]
 
	sealed trait TypeTree extends Tree

	// TYPES
	case object IntType extends TypeTree
	case object BoolType extends TypeTree
	case object StringType extends TypeTree
	case object ArrayType extends TypeTree

	// KEYWORDS
	sealed trait Class extends Tree with Symbolic[ClassSymbol]
 
	case class ClassDecl(id: Identifier, varDecls: List[VarDecl], metDecls: List[MethDecl]) extends Class
	case class ClassWithExtends(id : Identifier, superClass: Identifier, varDecls: List[VarDecl], metDecls: List[MethDecl]) extends Class

	case class VarDecl(id: Identifier, t: TypeTree) extends Tree with Symbolic[VariableSymbol]
	case class MethDecl(id: Identifier, args: List[Argument], returnType: TypeTree, throws: List[Identifier], varDecls: List[VarDecl], sts: Block, returnExpr: ExprTree) extends Tree with Symbolic[MethodSymbol]
 
	// CONTROLS
	case class While(test: ExprTree, stat: StatTree) extends StatTree
	case class If(test: ExprTree, stat: StatTree) extends StatTree
	case class IfElse(test: ExprTree, stat: StatTree, eStat: StatTree) extends StatTree
	case class Println(expr: ExprTree) extends StatTree

	case class Assign(id: Identifier, expr: ExprTree) extends StatTree
	case class AssignArrayCell(id: Identifier, idx: ExprTree, value: ExprTree) extends StatTree

	// EXCEPTIONS
	case class TryCatchBlock(body: Block, catches: List[Catch], finallyBlock: Option[Finally]) extends StatTree
	case class Catch(exceptionId: Identifier, exceptionType: Identifier, body: Block) extends StatTree
	case class Throw(exc: ExprTree) extends StatTree
    case class Finally(body: Block) extends StatTree
    
	sealed trait StatTree extends Tree
  
	case class Block(stats: List[StatTree]) extends StatTree
  
	sealed trait ExprTree extends Tree with Typed

	case class Plus(lhs: ExprTree, rhs: ExprTree)extends ExprTree
	case class Minus(lhs: ExprTree, rhs: ExprTree)extends ExprTree
	case class Times(lhs: ExprTree, rhs: ExprTree)extends ExprTree
	case class Div(lhs: ExprTree, rhs: ExprTree)extends ExprTree
	case class And(lhs: ExprTree, rhs: ExprTree)extends ExprTree
	case class Or(lhs: ExprTree, rhs: ExprTree)extends ExprTree
	case class Equals(lhs: ExprTree, rhs: ExprTree)extends ExprTree
	case class LessThan(lhs: ExprTree, rhs: ExprTree)extends ExprTree

	case class Not(v: ExprTree) extends ExprTree

	case class ArrayCell(tab: ExprTree, idx: ExprTree) extends ExprTree
	case class Length(tab: ExprTree) extends ExprTree
	case class MethodCall(instanceId: ExprTree, methodId: Identifier, args: List[ExprTree]) extends ExprTree
	
	case class IntLit(v: Int) extends ExprTree
	case class StringLit(s: String) extends ExprTree
	case class BoolLit(v: Boolean) extends ExprTree
	case class ArrayCreation(size: ExprTree) extends ExprTree
	case class Instanciation(t: Identifier) extends ExprTree
	case class Argument(id: Identifier, t: TypeTree) extends ExprTree with Symbolic[VariableSymbol]
	
	case class Identifier(value: String) extends TypeTree with ExprTree with Symbolic[Symbol]
}
